// ccterm.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"



#define TRUE 1
#define FALSE 0
#define FILE_ERROR 0

#define DECREMENT_HISTORY_TIME_LIMIT 1
#define REAL_TIME_DATA_SIZE 300
#define MAX_SENSORS 10
#define MAX_PROBES 3
#define WHOLE_HOUSE M
#define SINGLE_POLE S
#define TWO_POLE_D D
#define TWO_POLE_A A
#define THREE_POLE T
#define REAL_TIME_RECORD 1
#define HISTORY_RECORD 2

static HANDLE hSerial;


const char strCaption[] = "LogFile filter";
const char strSection[] = "LogFile";
const char strFilename[] = "filename";
const char strBinaryMode[] = "binarymode";
const char strWatts[] = "watts";
static char *ptrWatts;


#define BUFSIZE 4096 

static char init_file_name[] = "ccterm.ini";
static char LogFilename[MAX_PATH];
static char error_log_file_name[] = "ccmeter-log.txt";
static char history_file_name[] = "cchistory.txt";
static char archive_dir[MAX_PATH];
static char sensor_file_name[MAX_PATH];
static char sensor_init_file_name[] = "sensor.ini";
static char com_port[12];
static char run_raw[4] = {0};
static BOOL BinaryMode;
static FILE *fpCCmeter;
static FILE *fpHistory;
static FILE *fpLog;
static FILE *fpCcinit;
static FILE *fpSensor;
static FILE *fpSensor_init;
static BOOL LogTested;


//static int history_status = FALSE;


static struct {
	double interval_count;
	double watts_total;
	double watts_average;
	struct {
	char probe[5];
	char pv_param[4];
	char probe_type[3];
	double correction_factor;
	double watts;
	double watts_sub_total;
	} probes[MAX_PROBES];
} sensor_map[MAX_SENSORS];
	

static double watts_5_min_interval_count = 0;
static double watts_5_min_average;
static double watts_sub_total = 0;
static int in_session = FALSE;
static int in_5th_minute = FALSE;
static int no_history_dump = FALSE;

//static int history_running = FALSE;
//static int timer_running = FALSE;
//static time_t t_hist_start;
//static struct tm tm_hist_start;
//static int history_time_limit;
static int static_history_time_limit;
//static int history_end = FALSE;
static int days_to_archive = 0;


void print_time(void)
{
	time_t tim;
	struct tm *now;
	char *my_time;
	char s_my_time[80];
	int size;

	time(&tim);
	now=localtime(&tim);
	my_time = asctime(now);
	size = (int) strlen(my_time);
	my_time[size - 1] = '\0';
	strcpy(s_my_time,my_time);
	fprintf(fpLog,"%s: ",s_my_time);
	fflush(fpLog);
}


int init_params()
{
	char buffer[MAX_PATH];
	char s_history_time_limit[MAX_PATH];
	char *token;
	int return_status = TRUE;

	errno = 0;

	fpCcinit = fopen(init_file_name,"r");
	if (fpCcinit == NULL)
	{
		fprintf (fpLog,"Error opening INIT File - %s - %s\n",init_file_name,strerror(errno));
		fflush(fpLog);
		return FALSE;
	}
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(com_port,token);
	}else {
		return_status = FALSE;
	}
		
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(s_history_time_limit,token);
	}else {
		return_status = FALSE;
	}
	static_history_time_limit = atoi(s_history_time_limit);
	
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(LogFilename,token);
	}else {
		return_status = FALSE;
	}
		
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(archive_dir,token);
	}else {
		return_status = FALSE;
	}
	
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		days_to_archive = atoi(token);
	}else {
		return_status = FALSE;
	}
	
	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(sensor_file_name,token);
	}else {
		return_status = FALSE;
	}

	fgets(buffer,sizeof (buffer),fpCcinit);
	token = strtok(buffer,";");
	if(token != NULL)
	{
		strcpy(run_raw,token);
	}else {
		return_status = FALSE;
	}


	fclose(fpCcinit);

	return return_status;

}

int init_sensors()
{
	char buffer[MAX_PATH];
	char *buffer_ptr;
	char *token;
	int return_status = TRUE;
	int sensor_number = 0;
	int probe_number = 0;
	char temp_string[80];
	char *ptr_param;
	char *ptr_end;
	char s_correction_factor[10];

	errno = 0;

	fpSensor_init = fopen(sensor_init_file_name,"r");
	if (fpSensor_init == NULL)
	{
		fprintf (fpLog,"Error Opening Sensor Init File - %s - %s\n",sensor_init_file_name,strerror(errno));
		fflush(fpLog);
		return FALSE;
	}

	for(sensor_number = 0;sensor_number < MAX_SENSORS;sensor_number++){
		buffer_ptr = fgets(buffer,sizeof (buffer),fpSensor_init);
		token = strtok(buffer,";");
		
		if(token == NULL){
			print_time();
			fprintf(fpLog,"Sensor Initialization Reached EOF before MAX_SENSOR Count: %d\n",MAX_SENSORS);
			return FALSE;
		}
		memset(temp_string,0,sizeof(temp_string));
		
		strcpy(temp_string,token);
		strcat(temp_string,",");
		ptr_param = temp_string;
		for(probe_number = 0;probe_number < MAX_PROBES;probe_number++){
			sprintf(sensor_map[sensor_number].probes[probe_number].probe,"%d",probe_number);
			ptr_end = strchr(ptr_param,':');
			strncpy(sensor_map[sensor_number].probes[probe_number].pv_param,ptr_param,(ptr_end - ptr_param));
			ptr_param = ptr_end + 1;
			ptr_end = strchr(ptr_param,'-');
			strncpy(sensor_map[sensor_number].probes[probe_number].probe_type,ptr_param,(ptr_end - ptr_param));
			ptr_param = ptr_end + 1;
			ptr_end = strchr(ptr_param,',');
			memset(s_correction_factor,0,sizeof(s_correction_factor));
			strncpy(s_correction_factor,ptr_param,(ptr_end - ptr_param));
			sensor_map[sensor_number].probes[probe_number].correction_factor = atof(s_correction_factor);
			ptr_param = ptr_end + 1;
		}
	
	}
		

	fclose(fpSensor_init);

	return return_status;
}
int delete_archive_files(void)
{
	int return_status = TRUE;
	time_t time_now;
	struct tm *past;
	time_t archive_time_seconds;
	int archive_hour = 1;
	char archive_delete_name[MAX_PATH];


	
	time(&time_now);
		
	archive_time_seconds = time_now - (86400 * days_to_archive);
	past = localtime(&archive_time_seconds);

	while(archive_hour < 24){
		sprintf(archive_delete_name,"%s\\cchistory-%d%02d%02d-%02d.txt",
					archive_dir,(past->tm_year + 1900),(past->tm_mon + 1),past->tm_mday,archive_hour);
		remove(archive_delete_name);
		archive_hour = archive_hour + 2;
	}
	return return_status;
}

void get_time(char *time_now)
{
	time_t tim;
	struct tm *now;
	char *my_time;
	int size;

	time(&tim);
	now=localtime(&tim);
	my_time = asctime(now);
	size = (int) strlen(my_time);
	my_time[size - 1] = ':';
	my_time[size] = ' ';
	my_time[size + 1] = '\0';
	strcpy(time_now,my_time);
}


int record_sensor_data(int day,int month,int year,int hour,int minute,int second)
{
	int return_status = TRUE;
	int sensor_count = 0;
	int probe_count = 0;
	double watts_average = 0.0;
	double whole_house_total = 0.0;
	double watts_total = 0.0;
	int compare_status = 0;
	
	fprintf(fpSensor,"%02d.%02d.%d %02d:%02d:00;",
						day,month,year,hour,minute);

	fprintf(fpCCmeter,"%02d.%02d.%d %02d:%02d:00;",
						day,month,year,hour,minute);
	
	for(sensor_count = 0;sensor_count < MAX_SENSORS;sensor_count++){
		for(probe_count = 0;probe_count < MAX_PROBES;probe_count++){
			// This routine calculates the whole house power for either a two pole or three pole service
			watts_average = 0.0;
			compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"M");
			if(compare_status == 0){
				whole_house_total = whole_house_total + sensor_map[sensor_count].probes[probe_count].watts_sub_total;
				whole_house_total = whole_house_total * sensor_map[sensor_count].probes[probe_count].correction_factor;
				watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / 
																	sensor_map[sensor_count].interval_count;
				watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
				fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
												sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
				probe_count++;
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"M");
				if(compare_status == 0){

					watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / 
																	sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
												sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);

					whole_house_total = whole_house_total + sensor_map[sensor_count].probes[probe_count].watts_sub_total;
					whole_house_total = whole_house_total * sensor_map[sensor_count].probes[probe_count].correction_factor;
					probe_count++;
				}
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"M");
				if(compare_status == 0){
					watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / 
																	sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
												sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);

					whole_house_total = whole_house_total + sensor_map[sensor_count].probes[probe_count].watts_sub_total;
					whole_house_total = whole_house_total * sensor_map[sensor_count].probes[probe_count].correction_factor;
					probe_count++;
				}
				watts_average = whole_house_total / sensor_map[sensor_count].interval_count;
																	
				fprintf(fpCCmeter,"KWHR;%5.2f",watts_average);
			} // End of Whole House Routine

			// This routine is for any (non whole house) three pole circuit
			if(probe_count == 0){			// All three probes must be on one (1) sensor. If this fails, the sensor.ini file is
				watts_average = 0.0;		// misconfigured
				if(sensor_map[sensor_count].interval_count == 0) sensor_map[sensor_count].interval_count = 1;
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"T");
				if(compare_status == 0){
					watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / 
																	sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
												sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
					probe_count++;
					compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"T");
					if(compare_status == 0){
						watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total /
																	sensor_map[sensor_count].interval_count;
						watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
						fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
															sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
						probe_count++;
					}
					compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"T");
					if(compare_status == 0){
						watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total /
																	sensor_map[sensor_count].interval_count;
						watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
						fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
															sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
						probe_count++;
					}
					if(probe_count != MAX_PROBES){
						fprintf(fpLog,"Sensor.ini is misconfigured. All 3 TYPE T probes must be on Same Sensor\n");
						fflush(fpLog);
					}
				}  
			} // End of Three Pole Routine 

			// This routine calculates the average power for type D (a two pole circuit using one (1) probe)
			if(probe_count < (MAX_PROBES)){
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"D");
				if(compare_status == 0){
					watts_total = 0.0;
					watts_average = 0.0;
					watts_total = sensor_map[sensor_count].probes[probe_count].watts_sub_total * 2.0;
					if(sensor_map[sensor_count].interval_count == 0) sensor_map[sensor_count].interval_count = 1;
					watts_average = watts_total / sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
													sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
				}
			} // End of Type D routine

			if(probe_count < (MAX_PROBES)){
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"S");
				if(compare_status == 0){
					watts_total = 0.0;
					watts_average = 0.0;
					if(sensor_map[sensor_count].interval_count == 0) sensor_map[sensor_count].interval_count = 1;
					watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
													sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
				}
			}
			if(probe_count == 0 || probe_count == 1){
				compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"A");
				if(compare_status == 0){
					if(sensor_map[sensor_count].interval_count == 0) sensor_map[sensor_count].interval_count = 1;
					watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total / 
														sensor_map[sensor_count].interval_count;
					watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;				
					fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
													sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
					probe_count++;
					compare_status = strcmp(sensor_map[sensor_count].probes[probe_count].probe_type,"A");
					if(compare_status == 0 && probe_count < MAX_PROBES){
						watts_average = sensor_map[sensor_count].probes[probe_count].watts_sub_total /
														sensor_map[sensor_count].interval_count;
						watts_average = watts_average * sensor_map[sensor_count].probes[probe_count].correction_factor;
						fprintf(fpSensor,"%d,%d,%s,%.2f;",sensor_count,probe_count,
													sensor_map[sensor_count].probes[probe_count].pv_param,watts_average);
					}else {
						fprintf(fpLog,"Invalid TYPE A Configuration.  Check Sensor.ini File\n");
						fflush(fpLog);
					}
				}
			}
			fflush(fpSensor);
			fflush(fpCCmeter);
		} // probe_count loop
		fflush(fpSensor);
		fflush(fpCCmeter);
	} // sensor_count loop
	fprintf(fpCCmeter,"\n");
	fprintf(fpSensor,"\n");
	fflush(fpSensor);
	fflush(fpCCmeter);
	return return_status;
}
int reset_watts()
{
	int return_status = TRUE;
	int sensor_number = 0;
	int probe_number = 0;
	for(sensor_number = 0;sensor_number < MAX_SENSORS;sensor_number++){
		sensor_map[sensor_number].interval_count = 0.0;
		sensor_map[sensor_number].watts_average = 0.0;
		sensor_map[sensor_number].watts_total = 0.0;
		for(probe_number = 0;probe_number < MAX_PROBES;probe_number++){
			sensor_map[sensor_number].probes[probe_number].watts = 0.0;
			sensor_map[sensor_number].probes[probe_number].watts_sub_total = 0.0;
		}
	}
	return return_status;
}


double get_watts(char *data)
{
	double watts = 0.0;
	char *watts_ptr;
	// char *next_watts;
	char watts_value[10];
	char *watts_end_ptr;
	int watts_length;

	watts_ptr = strstr(data,"<watts>");
	watts_end_ptr = strstr(data,"</watts>");
	watts_ptr = watts_ptr + strlen("<watts>");
	watts_length = (int)(watts_end_ptr - watts_ptr);
	strncpy(watts_value,watts_ptr,watts_length);
	watts_value[watts_length] = '\0';
	watts = atof(watts_value);

	return watts;
}


char *check_channel(char *data,int channel_number)
{
	char s_channel_number[20];
	char *channel_ptr;
	char *watts_ptr = NULL;
	
	sprintf(s_channel_number,"<ch%d>",channel_number);
	channel_ptr = strstr(data,s_channel_number);
	if(channel_ptr != NULL){
		watts_ptr = channel_ptr;
	}
	return watts_ptr;
}


int get_sensor(char *data,int *sensor)
{
	int return_status = FALSE;

	char sensor_number[20] = {0};
	char *sensor_start;
	char *sensor_end;
	char *sensor_ptr;
		
	sensor_start = strstr(data,"<sensor>");
	if(sensor_start != NULL){
		sensor_end = strstr(data,"</sensor>");
		if(sensor_end != NULL){
			sensor_ptr = &sensor_start[strlen("<sensor>")];
			strncpy(sensor_number,sensor_ptr,1);
			*sensor = atoi(sensor_number);
			return_status = TRUE;
		}
	}
	return return_status;
}

int map_sensor_data(char *data,int size)
{
	int return_status = FALSE;
	int sensor_number = 0;
	int probe_number = 0;
	int sensor_status = TRUE;
	char *watts_ptr;
	double watts = 0;
	
	sensor_status = get_sensor(data,&sensor_number);
	if(sensor_status){
		sensor_map[sensor_number].interval_count++;
		return_status = TRUE;
		for(probe_number = 0;probe_number < MAX_PROBES;probe_number++){
			watts_ptr = check_channel(data,(probe_number + 1));  // Channels start with the Number One (1) (not zero (0))
			if(watts_ptr != NULL){
				watts = get_watts(watts_ptr);
				//if(sensor_number == 1 && probe_number == 2){
					//print_time();
					//fprintf(fpLog,"Found Sensor 1 and probe 2 (ch3) with Watts: %.2f  Data Size: %d\n",watts,size);
					//fflush(fpLog);
				//}
				sensor_map[sensor_number].probes[probe_number].watts = watts;
				sensor_map[sensor_number].probes[probe_number].watts_sub_total = 
								sensor_map[sensor_number].probes[probe_number].watts_sub_total +
									sensor_map[sensor_number].probes[probe_number].watts;
			}
		}
	}
	return return_status;
}


/* int check_history_timer(int current_status,int end)
{
	int return_status;
	time_t t_hist_now;
	struct tm *now;
	char new_history_name[MAX_PATH];
	char previous_history_name[MAX_PATH];
	char archive_history_name[MAX_PATH];
	char *token;
	int rename_status;

	return_status = current_status;
	if(timer_running)
	{
		return_status = TRUE;
		t_hist_now = time(NULL);
		now = localtime(&t_hist_now);

		if(end)
		{
			fclose(fpHistory);
			return_status = FALSE;
			timer_running = FALSE;
			history_time_limit = static_history_time_limit * 60;
			print_time();
			fprintf(fpLog,"End of History Dump Detected. History Timer Reset. History Dump Complete. History Dump File Closed\n");
			strcpy(previous_history_name,history_file_name);
			token = strtok(previous_history_name,".");
			sprintf(new_history_name,"%s-%d%02d%02d-%02d.txt",
				token,(now->tm_year + 1900),(now->tm_mon + 1),now->tm_mday,now->tm_hour);
			
			errno = 0;
			sprintf(archive_history_name,"%s\\%s",archive_dir,new_history_name);
			rename_status = rename(history_file_name,archive_history_name);
			print_time();
			if(rename_status == 0)
			{
				
				fprintf(fpLog,"History File Renamed to %s\n",archive_history_name);
			}else{
				fprintf(fpLog,"History File Rename Failed: %s.  Old File Name: %s  New File Name: %s\n",
																		strerror(errno),history_file_name,archive_history_name);
			}
		}else{
			history_time_limit = history_time_limit - DECREMENT_HISTORY_TIME_LIMIT;
			if(((t_hist_now - t_hist_start) > history_time_limit) && !end)
			{
				fclose(fpHistory);
				return_status = FALSE;
				timer_running = FALSE;
				history_time_limit = static_history_time_limit * 60;
				print_time();
				fprintf(fpLog,"History Timer Expired While Writing History File - !INCREASE HISTORY TIMEOUT VALUE! - History Dump File Closed \n");
			}
		}
	}
	fflush(fpLog);
	return return_status;
}
*/

int write_cc_dump(char *data,int size,int start,int end)
{
	int return_status = FALSE;
	char my_time[80];
	time_t t_hist_now;
	struct tm *now;

	char new_history_name[MAX_PATH];
	char previous_history_name[MAX_PATH];
	char archive_history_name[MAX_PATH];
	char *token;
	int rename_status;

	
	if(start)  // start of history dump
	{
		return_status = TRUE;
		//timer_running = TRUE;
		errno = 0;
		print_time();
		fprintf(fpLog,"Opening History File\n");
		fpHistory = fopen(history_file_name,"w");
		if (fpHistory == NULL)
			{
				print_time();
				fprintf(fpLog,"History File Open Failed: %s",strerror(errno));
				return_status = FALSE;
			}
		//history_time_limit = history_time_limit - DECREMENT_HISTORY_TIME_LIMIT;
		print_time();
		fprintf(fpLog,"Starting History Dump.\n");
		get_time(my_time);
		fwrite(my_time,1,(size_t) strlen(my_time),fpHistory);
		fwrite("\n",1,(size_t) strlen("\n"),fpHistory);
		fwrite(data,(size_t) size,1,fpHistory);
		fflush(fpHistory);
		
	}else {  // History dump has already started.  The function: check_history_timer - will check for the end of the history dump
			return_status = TRUE;
			fwrite(data,(size_t) size,1,fpHistory);
			fflush(fpHistory);
		if(end){
			t_hist_now = time(NULL);
			now = localtime(&t_hist_now);
			fclose(fpHistory);
			return_status = FALSE;
			//timer_running = FALSE;
			print_time();
			fprintf(fpLog,"End of History Dump Detected. History Dump Complete. History Dump File Closed\n");
			strcpy(previous_history_name,history_file_name);
			token = strtok(previous_history_name,".");
			sprintf(new_history_name,"%s-%d%02d%02d-%02d.txt",
				token,(now->tm_year + 1900),(now->tm_mon + 1),now->tm_mday,now->tm_hour);
			
			errno = 0;
			sprintf(archive_history_name,"%s\\%s",archive_dir,new_history_name);
			rename_status = rename(history_file_name,archive_history_name);
			print_time();
			if(rename_status == 0){
				fprintf(fpLog,"History File Renamed to %s\n",archive_history_name);
			}else{
				fprintf(fpLog,"History File Rename Failed: %s.  Old File Name: %s  New File Name: %s\n",
																		strerror(errno),history_file_name,archive_history_name);
			}
		}
	}
	fflush(fpLog);
	return return_status;
}

int history_end_check(char *data,int size)
{
	char *temp_check;
	int status = FALSE;
	temp_check = strstr(data,"</m001>");
	if(temp_check != NULL)
	{
		status = TRUE;
	}
	return status;
}
		
int valid_data_check(char *data)
{
	int return_status = FALSE;
	char *sensor_ptr;
	
	sensor_ptr = strstr(data,"<msg>");;
	if(sensor_ptr != NULL){
		sensor_ptr = strstr(data,"</msg>");
		if(sensor_ptr != NULL){
			return_status = TRUE;
		}
	}
	return return_status;
}


	
int history_record(char *Text,int size)
{
	static int history_start = FALSE;
	static int history_end = FALSE;

	if(!no_history_dump){
		history_end = history_end_check(Text,size);
		if(history_start == FALSE){
			history_start = TRUE;
			history_start = write_cc_dump(Text,size,history_start,history_end);
		}else{
			history_start = FALSE;
			history_start = write_cc_dump(Text,size,history_start,history_end);
		}
	}
	return TRUE;
}

int real_time_record(char *Text, int Size)
{
	int watts_status = FALSE;
	int return_status = FALSE;
	static int reported_5_minute_data = FALSE;
	static int in_5th_minute = FALSE;
	static int just_started = TRUE;

		// This routine collects the 10 second data and averages it over 5 minutes. It starts at 0 and ends at the beginning of 
        // minute 5. Ex: Minutes 0,1,2,3,4 - At beginning of minute 5 record report.  5,6,7,8,9 - At beginning of minute 10 record report. 
        // This (I believe) coincides with the method Sunny Explorer reports five minute data (such as it reports average power up to
        // the five minute mark. But this is only a guess as SMA is not forthcoming with the exact information.

	
	time_t tim=time(NULL);
	struct tm *now=localtime(&tim);
		
	if(now->tm_min%5 == 0 || now->tm_min == 0){  // The minute is divisible by 5 or the minute is 0
		if(!just_started){ // The program started in the 5th minute.  The values will not be valid. Skip this first 5th minute.
			if(!reported_5_minute_data){ // At start of 5th minute report the 5 minute data
				watts_status = record_sensor_data(now->tm_mday,(now->tm_mon + 1),
													(now->tm_year + 1900), now->tm_hour,now->tm_min,now->tm_sec);
				watts_status = reset_watts();
				// history_status = check_history_timer(history_status,history_end); // Check for end of history dump
				return_status = delete_archive_files();  // Delete archived history files based on the init parameter
				reported_5_minute_data = TRUE;
					
			} else{ // In the 5th minute.  Collect the 5th minute data
				watts_status = map_sensor_data(Text,Size);
			}
		}
	}else{ // Not in a 5th minute period. 
		just_started = FALSE;
		reported_5_minute_data = FALSE;
		watts_status = map_sensor_data(Text,Size);
	}
	return TRUE;
}


int parse_record(char *data,int size,int record_raw,FILE *fpRaw)
{
	int status = TRUE;
	char *record_start = NULL;
	char *record_stop = NULL;
	char *data_record_end = NULL;
	char *record_type = NULL;
	char my_time[80];
	int record_size = 0;
	int count = 0;

	data_record_end = data + size;
	record_start = strstr(data,"<msg>");
	if(record_start == NULL){
		print_time();
		fprintf(fpLog,"Parse Record Start: Invalid Data Record: Start Token Missing - Discarding Record\n");
		status = FALSE;
		fflush(fpLog);
	}
	if(record_start != NULL){
		record_stop = strstr(record_start,"</msg>");
		while((record_stop < data_record_end) && (record_stop != NULL) && (record_start != NULL)){
			record_stop = strstr(record_start,"</msg>");
			if(record_stop != NULL){
				record_stop = record_stop + (strlen("</msg")) + 3;
				record_size = record_stop - record_start;
				record_type = strstr(record_start,"<tmpr");
				if(record_type != NULL){
					status = real_time_record(record_start,record_size);
				} else {
					record_type = strstr(record_start,"<hist>");
					if(record_type != NULL){
						status = history_record(record_start,record_size);
					}
				}
				
				if(record_raw){
					get_time(my_time);
					fprintf(fpRaw,"\n");
					fwrite(my_time,1,(size_t) strlen(my_time),fpRaw);
					fprintf(fpRaw,"Parse Record Count: %d  Parse Record Size: %d \n",++count,record_size);
					fwrite(record_start,(size_t) record_size,1,fpRaw);
					fflush(fpRaw);
				}
				record_start = strstr(record_stop,"<msg>");
			}else{
			  print_time();
			  fprintf(fpLog,"Parse Record Stop: Invalid Record: End Token Missing - Discarding Record \n");
			  fflush(fpLog);
			  status = FALSE;
			}
		}
	}
	return status;
}
  
int open_com_port()
{
	int status = TRUE;

	DCB dcbSerialParams = {0};
	COMMTIMEOUTS timeouts={0};
	char lastError[1024];

	hSerial = CreateFile(com_port,
				GENERIC_READ | GENERIC_WRITE,
				0,
				0,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				0);

	if(hSerial==INVALID_HANDLE_VALUE){
		if(GetLastError() == ERROR_FILE_NOT_FOUND){
			print_time();
			fprintf(fpLog,"COM Port: %s Open Failed \n",com_port);
		}
		FormatMessage(
		FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		ERROR_FILE_NOT_FOUND,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		lastError,
		1024,
		NULL);
		print_time();
		fprintf(fpLog,"Error Opening Com Port: %s %s\n",com_port,lastError);
		status = FALSE;
	}


	if(status){
		dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
		if (!GetCommState(hSerial, &dcbSerialParams)) {
			FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			lastError,
			1024,
			NULL);
			print_time();
			fprintf(fpLog,"Error Retrieving serial port state %s\n",lastError);
			status = FALSE;
		}
	}

	dcbSerialParams.BaudRate=CBR_57600;
	dcbSerialParams.ByteSize=8;
	dcbSerialParams.StopBits=ONESTOPBIT;
	dcbSerialParams.Parity=NOPARITY;

	if(status){
		if(!SetCommState(hSerial, &dcbSerialParams)){
			FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			lastError,
			1024,
			NULL);
			print_time();
			fprintf(fpLog,"Error Setting serial port state %s\n",lastError);
			status = FALSE;
		}
	}

	
	timeouts.ReadIntervalTimeout=6;
	timeouts.ReadTotalTimeoutConstant=4;
	timeouts.ReadTotalTimeoutMultiplier=3;
	timeouts.WriteTotalTimeoutConstant=50;
	timeouts.WriteTotalTimeoutMultiplier=10;


	if(status){
		if(!SetCommTimeouts(hSerial, &timeouts)){
			FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			lastError,
			1024,
			NULL);
			print_time();
			fprintf(fpLog,"Error Setting serial port timeouts %s\n",lastError);
			status = FALSE;
		}
	}
	fflush(fpLog);
	return status;
}

int archive_logfile(int year,int month,int day)
{
	char temp_name[MAX_PATH];
	char archive_name[MAX_PATH];
	char archive_log_name[MAX_PATH];
	char *token;
	int return_status = TRUE;
	int rename_status = TRUE;

	fclose(fpLog);
	strcpy(temp_name,error_log_file_name);
	token = strtok(temp_name,".");
	sprintf(archive_name,"%s-%d%02d%02d.txt",
		token,year,month,day);
			
	errno = 0;
	sprintf(archive_log_name,"%s\\%s",archive_dir,archive_name);
	rename_status = rename(error_log_file_name,archive_log_name);
	fpLog = fopen(error_log_file_name,"at");
	return return_status;
}

int _tmain(int argc, _TCHAR* argv[])
{
  
	int n = 8192;
	char szBuff[8196] = {0};
	DWORD dwBytesRead = 0;
	char lastError[1024];
	static BOOL com_read_status = TRUE;
	// FILE *sensor_test;
	char my_time[80] = {0};
	FILE *fpRaw = NULL;
	int raw_mode = FALSE;
		
	int status = FALSE;
	int parse_status = FALSE;
	int in_odd_start_hour = FALSE;
	int program_just_started = TRUE;
	time_t tim;
	struct tm *now;

		
	fpLog = fopen(error_log_file_name,"at");
	if(fpLog == NULL)
	{
		perror("CC Log File Open Failed: ");
		printf("Program Terminating\n");
		exit (FALSE);
	}

	
	status = init_params();
	if(!status){
		print_time();
		fprintf(fpLog,"Initialization of Parameters Failed\n");
		fflush(fpLog);
		Beep(1000, 500);
		exit(FALSE);
	}

	errno = 0;
	fpCCmeter = fopen(LogFilename,"at");
	if(fpCCmeter == NULL)
	{
		print_time();
		fprintf(fpLog,"CC Data File Open Failed	with Error: %s   Program Terminating\n",strerror(errno));
		exit(FALSE);
	}

	status = init_sensors();
	if(!status){
		print_time();
		fprintf(fpLog,"Initialization of Sensor Map Failed\n");
		fflush(fpLog);
		exit(FALSE);
	}

	errno = 0;
	fpSensor = fopen(sensor_file_name,"at");
	if(fpSensor == NULL)
	{
		print_time();
		fprintf(fpLog,"Sensor Data File Open Failed	with Error: %s   Program Terminating\n",strerror(errno));
		exit(FALSE);
	}

	if((strcmp(run_raw,"Y")) == 0){
		raw_mode = TRUE;
		print_time();
		fprintf(fpLog,"Tracing Enabled - CC Trace Data will be Recorded to: trace-data.txt\n");
	}

	if(raw_mode){
		fpRaw = fopen("trace-data.txt","wt");
		if(fpRaw == NULL){
			print_time();
			fprintf(fpLog,"Trace Data File Open Failed - Tracing Disabled \n");
			raw_mode = FALSE;
		}
	}

   if(!SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS))
   {
     	FormatMessage(
		FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		GetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		lastError,
		1024,
		NULL);
		print_time();
		fprintf(fpLog,"Error Setting CCTERM Priority %s\n",lastError);
		fflush(fpLog);
		
   } 

	//history_time_limit = static_history_time_limit * 60;
	status = reset_watts();
			
	parse_status = open_com_port();
	if(!parse_status){
		print_time();
		fprintf(fpLog,"Com Port Open Failed.  Com Port:%s  Program Terminating\n",com_port);
		fflush(fpLog);
		exit(FALSE);
	}

	print_time();
	fprintf(fpLog,"CCTERM Started and Initialized. \n");
	fflush(fpLog);


	errno = 0;

	/*sensor_test = fopen("sensor-input.txt","r");
	
	if(sensor_test == NULL)
	{
		print_time();
		fprintf(fpLog,"Senor Input Open Failed	with Error: %s   Program Terminating\n",strerror(errno));
		exit(FALSE);
	}

	dwBytesRead = 4000;
	while((fgets(szBuff,(int) dwBytesRead,sensor_test)) != NULL){
		time(&tim);										// If so wait until next Odd Hour
		now=localtime(&tim);							// So to avoid obtaining a partial dump 
		if(now->tm_hour%2 != 0 && program_just_started){
		in_odd_start_hour = TRUE;
		no_history_dump = TRUE;
		program_just_started = FALSE;
		print_time();
		fprintf(fpLog,"CC TERM has started in an Odd Hour.  CC History Dumps will start in the Next Odd Hour\n");
		fflush(fpLog);
		}else{
			program_just_started = FALSE;
			if(in_odd_start_hour)
			{
				if(now->tm_hour%2 == 0)
				{
					in_odd_start_hour = FALSE;
					no_history_dump = FALSE;
				}
			}
		}
		flt_Receive(szBuff, (strlen(szBuff)));
	}*/
	
	// status = TRUE;
	while((com_read_status) && (parse_status)) {
		memset(szBuff,0,sizeof(szBuff));
		if(!(com_read_status = ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL))){
			FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			lastError,
			1024,
			NULL);
			print_time();									
			fprintf(fpLog,"Error Reading Com Port %s.  Program is terminating\n",lastError);
			fflush(fpLog);
		}else {                                             // Check if CCTERM has started in an Odd Hour
			time(&tim);										// If so wait until next Odd Hour
			now=localtime(&tim);							// So to avoid obtaining a partial dump 
			// Archive the Log File
			if((now->tm_hour == 23) && (now->tm_min >= 58)){
					archive_logfile((now->tm_year + 1900),(now->tm_mon + 1),now->tm_mday);
			}
			if(now->tm_hour%2 != 0 && program_just_started){
				in_odd_start_hour = TRUE;
				no_history_dump = TRUE;
				program_just_started = FALSE;
				print_time();
				fprintf(fpLog,"CC TERM has started in an Odd Hour.  CC History Dumps will start in the Next Odd Hour\n");
				fflush(fpLog);
			}else{
				program_just_started = FALSE;
				if(in_odd_start_hour)
				{
					if(now->tm_hour%2 == 0)
					{
						in_odd_start_hour = FALSE;
						no_history_dump = FALSE;
					}
				}
			}
			if(raw_mode){
				fprintf(fpRaw,"\n");
				get_time(my_time);
				fwrite(my_time,1,(size_t) strlen(my_time),fpRaw);
				fprintf(fpRaw,"Com Port Data - Size: %d \n",dwBytesRead);
				fwrite(szBuff,(size_t) dwBytesRead,1,fpRaw);
				fflush(fpRaw);
			}
			if(dwBytesRead > 0){
				parse_status = parse_record(szBuff, (int) dwBytesRead,raw_mode,fpRaw);
			}
			if(!parse_status){
				CloseHandle(hSerial);
				print_time();
				fprintf(fpLog,"Record Parsing Failed. Reopening Com Port\n");
				fflush(fpLog);
				com_read_status = TRUE;
				parse_status = open_com_port();
			}
		} // End ELSE ReadFile
	} // End While 
	CloseHandle(hSerial);					// If we get this far the com port Open or Read failed
	print_time();
	fprintf(fpLog,"Com Port Open or Read failed with a Critical Error.  Program Terminating\n");
	fflush(fpLog);
	exit(FALSE);
}
